import UIKit
import Photos
import PhotosUI

// 添加代理协议
protocol YCPhotoPreviewCellDelegate: AnyObject {
    func cellDidBeginDragging(_ cell: YCPhotoPreviewCell)
    func cell(_ cell: YCPhotoPreviewCell, didDragWithProgress progress: CGFloat)
    func cellDidEndDragging(_ cell: YCPhotoPreviewCell, shouldDismiss: Bool)
    func cellDidCancelDragging(_ cell: YCPhotoPreviewCell)
}

class YCPhotoPreviewCell: UICollectionViewCell {
    
    // MARK: - Properties
    
    public let scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.minimumZoomScale = 1.0
        scrollView.maximumZoomScale = 3.0
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        scrollView.clipsToBounds = true
        scrollView.contentInsetAdjustmentBehavior = .never
        scrollView.bouncesZoom = true
        return scrollView
    }()
    
    public let containerView: UIView = {
        let view = UIView()
        view.backgroundColor = .clear
        return view
    }()
    
    public let imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()
    
    public let livePhotoView: PHLivePhotoView = {
        let view = PHLivePhotoView()
        view.contentMode = .scaleAspectFit
        view.isHidden = true
        return view
    }()
    
    private let indicatorContainerView: UIView = {
        let view = UIView()
        return view
    }()
    
    private let livePhotoIndicator: UIImageView = {
        let config = UIImage.SymbolConfiguration(pointSize: 24, weight: .medium)
        let image = UIImage(systemName: "livephoto", withConfiguration: config)
        let imageView = UIImageView(image: image)
        imageView.tintColor = .white
        imageView.contentMode = .scaleAspectFit
        imageView.isHidden = true
        return imageView
    }()
    
    var asset: PHAsset?
    private let imageManager = PHCachingImageManager()
    private var livePhotoRequestID: PHImageRequestID?
    private var imageRequestID: PHImageRequestID?
    private var thumbnailRequestID: PHImageRequestID?
    
    private var longPressGesture: UILongPressGestureRecognizer?
    
    // 添加代理属性
    weak var delegate: YCPhotoPreviewCellDelegate?
    
    // 添加拖动手势相关属性
    private var panGesture: UIPanGestureRecognizer!
    public var initialCenter: CGPoint = .zero
    
    // 在 YCPhotoPreviewCell 类中添加初始触摸点位置跟踪
    private var initialTouchPoint: CGPoint = .zero
    
    private var displayFrame: CGRect = .zero {
        didSet {
            // 更新 containerView 的 frame
            containerView.frame = displayFrame
            // 更新子视图的 frame
            imageView.frame = containerView.bounds
            livePhotoView.frame = containerView.bounds
            // 更新 scrollView 的 contentSize
            scrollView.contentSize = displayFrame.size
        }
    }
    
    // MARK: - Initialization
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - Setup
    
    private func setupUI() {
        // 添加锚点配置
        containerView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        contentView.addSubview(scrollView)
        scrollView.addSubview(containerView)
        containerView.addSubview(imageView)
        containerView.addSubview(livePhotoView)
        
        // 将 indicator 容器添加到 containerView 上
        containerView.addSubview(indicatorContainerView)
        indicatorContainerView.addSubview(livePhotoIndicator)
        
        // 设置 indicatorContainerView 的固定位置和大小
        let indicatorSize: CGFloat = 20
        
        indicatorContainerView.frame = CGRect(x: 15, y: 15, width: indicatorSize, height: indicatorSize)
        // 设置图标位置
        livePhotoIndicator.frame = CGRect( x: 0, y: 0, width: indicatorSize, height: indicatorSize)
        
        scrollView.delegate = self
        
        // 添加手势识别器
        let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(_:)))
        doubleTapGesture.numberOfTapsRequired = 2
        scrollView.addGestureRecognizer(doubleTapGesture)
        
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
        longPress.minimumPressDuration = 0.3
        scrollView.addGestureRecognizer(longPress)
        self.longPressGesture = longPress
        
        livePhotoView.delegate = self
        
        // 添加拖动手势
        panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
        panGesture.delegate = self
        scrollView.addGestureRecognizer(panGesture)
    }
    
    // MARK: - Configuration
    
    func configure(with asset: PHAsset) {
        // 如果正在加载同一资源，则不需要重新加载
        if self.asset?.localIdentifier == asset.localIdentifier {
            return
        }
        
        self.asset = asset
        
        // 重置缩放
        scrollView.zoomScale = 1.0
        
        // 检查是否是 LivePhoto
        let isLivePhoto = asset.mediaSubtypes.contains(.photoLive)
        
        // 重要：初始时不要立即隐藏 imageView，等缩略图加载后再隐藏
        if isLivePhoto {
            // 对于 LivePhoto 同时显示 imageView 和 livePhotoView，等 LivePhoto 加载完成再隐藏 imageView
            imageView.isHidden = false
            livePhotoView.isHidden = false
            livePhotoIndicator.isHidden = false
            
            // 先清空 LivePhoto 内容，避免显示旧的内容
            livePhotoView.livePhoto = nil
        } else {
            imageView.isHidden = false
            livePhotoView.isHidden = true
            livePhotoIndicator.isHidden = true
        }
        
        // 首先加载缩略图
        loadThumbnailImage(asset: asset)
        
        // 然后加载高质量图片或 LivePhoto
        if isLivePhoto {
            loadLivePhoto(asset: asset)
        } else {
            loadImage(asset: asset)
        }
    }
    
    private func loadImage(asset: PHAsset) {
        // 高质量图片加载
        let options = PHImageRequestOptions()
        options.deliveryMode = .highQualityFormat
        options.isNetworkAccessAllowed = true
        options.version = .current
        options.resizeMode = .fast
        
        imageRequestID = imageManager.requestImage(
            for: asset,
            targetSize: PHImageManagerMaximumSize,
            contentMode: .aspectFit,
            options: options
        ) { [weak self] image, info in
            // 检查请求是否被取消
            if let cancelled = info?[PHImageCancelledKey] as? Bool, cancelled {
                return
            }
            
            // 检查请求是否出错
            if let error = info?[PHImageErrorKey] as? Error {
                print("Image request error: \(error.localizedDescription)")
                return
            }
            
            guard let self = self,
                  let highQualityImage = image else { return }
            
            // 检查是否仍需要显示此图片
            if self.asset?.localIdentifier != asset.localIdentifier {
                return
            }
            
            DispatchQueue.main.async {
                self.imageView.image = highQualityImage
                self.updateImageViewConstraints(for: highQualityImage)
            }
        }
    }
    
    private func loadLivePhoto(asset: PHAsset) {
        let options = PHLivePhotoRequestOptions()
        options.deliveryMode = .highQualityFormat
        options.isNetworkAccessAllowed = true
        options.version = .current  // 使用当前版本，避免触发系统变更通知
                
        livePhotoRequestID = imageManager.requestLivePhoto(
            for: asset,
            targetSize: PHImageManagerMaximumSize,
            contentMode: .aspectFit,
            options: options
        ) { [weak self] livePhoto, info in
            guard let self = self,
                  let livePhoto = livePhoto,
                  self.asset?.localIdentifier == asset.localIdentifier else {
                return
            }
            
            DispatchQueue.main.async {
                
                // 设置 LivePhoto
                self.livePhotoView.livePhoto = livePhoto
                // 这样可以避免黑屏问题
                if self.livePhotoView.livePhoto != nil {
                    self.imageView.isHidden = true
                }
                // 更新 LivePhoto 视图大小
                self.updateLivePhotoViewConstraints(for: livePhoto.size)
            }
        }
    }
    
    private func loadThumbnailImage(asset: PHAsset) {
        let thumbnailSize = CGSize(width: 400, height: 400)
        let thumbnailOptions = PHImageRequestOptions()
        thumbnailOptions.deliveryMode = .fastFormat
        thumbnailOptions.isNetworkAccessAllowed = true
        thumbnailOptions.version = .current  // 使用当前版本，避免触发系统变更通知
        thumbnailOptions.isSynchronous = false
        
        // 清除之前的缩略图
        imageView.image = nil
        
        thumbnailRequestID = imageManager.requestImage(
            for: asset,
            targetSize: thumbnailSize,
            contentMode: .aspectFill,
            options: thumbnailOptions
        ) { [weak self] image, info in
            guard let self = self,
                  let thumbnailImage = image,
                  self.asset?.localIdentifier == asset.localIdentifier else { return }
            
            DispatchQueue.main.async {
                // 无论是否是 LivePhoto，都先显示缩略图
                self.imageView.isHidden = false
                self.imageView.image = thumbnailImage
                self.updateImageViewConstraints(for: thumbnailImage)
            }
        }
    }
    
    private func updateImageViewConstraints(for image: UIImage) {
        updateDisplayFrame(size: image.size)
    }
    
    private func updateLivePhotoViewConstraints(for size: CGSize) {
        updateDisplayFrame(size: size)
    }
    
    private func updateDisplayFrame(size: CGSize) {
        let viewSize = bounds.size
        
        let widthRatio = viewSize.width / size.width
        let heightRatio = viewSize.height / size.height
        let aspectRatio = min(widthRatio, heightRatio)
        
        let scaledWidth = size.width * aspectRatio
        let scaledHeight = size.height * aspectRatio
        
        displayFrame = CGRect(
            x: (viewSize.width - scaledWidth) / 2,
            y: (viewSize.height - scaledHeight) / 2,
            width: scaledWidth,
            height: scaledHeight
        )
        print("图片位置为：\(displayFrame)")
    }
    
    // MARK: - Actions
    
    @objc private func handleDoubleTap(_ gesture: UITapGestureRecognizer) {
        if scrollView.zoomScale > 1.0 {
            scrollView.setZoomScale(1.0, animated: true)
        } else {
            
            // 获取点击位置在 containerView 中的坐标
            let tapPoint = gesture.location(in: containerView)
            let scale = scrollView.maximumZoomScale
            let zoomRect = calculateZoomRect(centerPoint: tapPoint, scale: scale)
            scrollView.zoom(to: zoomRect, animated: true)
        }
    }
    
    private func calculateZoomRect(centerPoint: CGPoint, scale: CGFloat) -> CGRect {
        let size = CGSize(
            width: scrollView.frame.width / scale,
            height: scrollView.frame.height / scale
        )
        
        // 边界保护：确保 origin 不会超出内容范围
        let originX = max(0, min(centerPoint.x - size.width/2, containerView.bounds.width - size.width))
        let originY = max(0, min(centerPoint.y - size.height/2, containerView.bounds.height - size.height))
        
        return CGRect(
            origin: CGPoint(x: originX, y: originY),
            size: size
        )
    }
    
    @objc private func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
        guard !livePhotoView.isHidden else { return }
        
        switch gesture.state {
        case .began:
            // 开始长按时播放
            livePhotoView.startPlayback(with: .full)
            
            // 添加触感反馈
            let feedback = UIImpactFeedbackGenerator(style: .medium)
            feedback.impactOccurred()
            
        case .ended, .cancelled:
            // 结束长按时停止播放
            livePhotoView.stopPlayback()
            
        default:
            break
        }
    }
    
    // 在 YCPhotoPreviewCell 类中添加判断拖动方向的方法
    private func isDragDirectionValid(_ velocity: CGPoint) -> Bool {
        // 允许在90度范围内的拖动 (下方45度到右下45度再到左下45度)
        // 纯水平方向不允许（避免干扰图片切换）
        let angle = atan2(velocity.y, velocity.x)
        let isHorizontal = abs(angle) < CGFloat.pi / 12 || abs(angle) > CGFloat.pi * 11 / 12
        
        // 允许垂直向下和向斜下方45度范围内的拖动
        return !isHorizontal && velocity.y > 0
    }

    // 处理拖动手势
    @objc private func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: scrollView)
        let velocity = gesture.velocity(in: scrollView)
        
        switch gesture.state {
        case .began:
            // 记录初始触摸点和容器中心点
            initialTouchPoint = gesture.location(in: scrollView)
            initialCenter = containerView.center
            delegate?.cellDidBeginDragging(self)
            
        case .changed:
            // 计算当前触摸点相对于初始触摸点的垂直偏移
            let currentOffset = translation.y
            
            // 应用阻尼效果，使拖动感觉更自然
            let dampenedY = currentOffset * 0.7
            let dampenedX = translation.x * 0.5 // 水平方向阻尼更强
            
            // 更新容器位置
            containerView.center = CGPoint(
                x: initialCenter.x + dampenedX,
                y: initialCenter.y + dampenedY
            )
            
            // 仅当向下拖动时（Y值增加）才应用缩放和背景变化
            if currentOffset > 0 {
                // 计算下拉进度，用于动画
                let progress = currentOffset / (bounds.height * 0.4)
                
                // 计算缩放比例 - 向下拖动缩小
                let scale = max(0.6, 1.0 - progress * 0.3)
                containerView.transform = CGAffineTransform(scaleX: scale, y: scale)
                
                // 通知代理更新UI，传递正进度值表示向下拖动
                delegate?.cell(self, didDragWithProgress: progress)
            } else {
                // 向上拖动时保持原始大小
                containerView.transform = .identity
                
                // 通知代理停留在原始状态，传递0表示没有缩放或背景变化
                delegate?.cell(self, didDragWithProgress: 0)
            }
            
        case .ended, .cancelled:
            // 只有向下拖动时才考虑关闭
            if translation.y > 0 {
                // 定义关闭阈值
                let dismissThreshold: CGFloat = 150
                let velocityThreshold: CGFloat = 800
                
                // 决定是否应该关闭 - 只有向下拖动超过阈值才关闭
                let shouldDismiss = (translation.y > dismissThreshold && velocity.y > 0) || 
                                    (velocity.y > velocityThreshold)
                
                if gesture.state == .ended {
                    delegate?.cellDidEndDragging(self, shouldDismiss: shouldDismiss)
                } else {
                    delegate?.cellDidCancelDragging(self)
                }
            } else {
                // 向上拖动直接回弹，不考虑关闭
                delegate?.cellDidCancelDragging(self)
            }
            
        default:
            break
        }
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        
        // 取消所有请求并重置视图
        cancelPendingRequests()
        
        imageView.alpha = 1.0  // 确保透明度正常
        scrollView.zoomScale = 1.0
    }
    
    // MARK: - Layout
    
    override func layoutSubviews() {
        super.layoutSubviews()
        scrollView.frame = contentView.bounds
        
        // 如果 displayFrame 已经设置，在布局变化时保持比例
        if displayFrame != .zero {
            if let image = imageView.image {
                updateDisplayFrame(size: image.size)
            } else if let livePhoto = livePhotoView.livePhoto {
                updateDisplayFrame(size: livePhoto.size)
            }
        }
    }
    
    // 将取消请求的逻辑拆分为两个方法
    // 1. 取消所有未完成的请求但不清空已加载的图片
    private func cancelPendingRequests() {
        if let requestID = imageRequestID {
            imageManager.cancelImageRequest(requestID)
            imageRequestID = nil
        }
        
        if let requestID = thumbnailRequestID {
            imageManager.cancelImageRequest(requestID)
            thumbnailRequestID = nil
        }
        
        if let requestID = livePhotoRequestID {
            imageManager.cancelImageRequest(requestID)
            livePhotoRequestID = nil
        }
        
        // 停止 LivePhoto 播放但不清空内容
        livePhotoView.stopPlayback()
    }
    
    // 1. 添加一个公开的方法用于取消和重新加载图片
    func cancelLoading() {
        cancelPendingRequests()
    }
    
    // 2. 添加一个公开的方法用于强制重新加载当前图片
    func reloadAsset() {
        if let currentAsset = asset {
            // 检查是否是 LivePhoto
            let isLivePhoto = currentAsset.mediaSubtypes.contains(.photoLive)
            
            // 首先加载缩略图
            loadThumbnailImage(asset: currentAsset)
            
            // 然后加载高质量图片或 LivePhoto
            if isLivePhoto {
                loadLivePhoto(asset: currentAsset)
            } else {
                loadImage(asset: currentAsset)
            }
        }
    }
    
    // 5. 添加一个方法来标记当前 cell 是否可见
    func setVisible(_ isVisible: Bool) {
        Thread.current.threadDictionary["isVisibleCell"] = isVisible
        
        // 如果变为可见但图片未加载，尝试重新加载
        if isVisible && ((self.imageView.image == nil && !asset!.mediaSubtypes.contains(.photoLive)) || 
                        (asset!.mediaSubtypes.contains(.photoLive) && self.livePhotoView.livePhoto == nil)) {
            reloadAsset()
        }
    }
}

// MARK: - UIScrollViewDelegate

extension YCPhotoPreviewCell: UIScrollViewDelegate {
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return containerView
    }
    
    func scrollViewDidZoom(_ scrollView: UIScrollView) {
        // 增加边界补偿
        let offsetX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
        let offsetY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
        containerView.center = CGPoint(
            x: scrollView.contentSize.width * 0.5 + offsetX,
            y: scrollView.contentSize.height * 0.5 + offsetY
        )
    }
}

// MARK: - PHLivePhotoViewDelegate

extension YCPhotoPreviewCell: PHLivePhotoViewDelegate {
    func livePhotoView(_ livePhotoView: PHLivePhotoView, willBeginPlaybackWith playbackStyle: PHLivePhotoViewPlaybackStyle) {
        UIView.animate(withDuration: 0.2) {
            self.indicatorContainerView.alpha = 0
        }
    }
    
    func livePhotoView(_ livePhotoView: PHLivePhotoView, didEndPlaybackWith playbackStyle: PHLivePhotoViewPlaybackStyle) {
        UIView.animate(withDuration: 0.2) {
            self.indicatorContainerView.alpha = 1
        }
    }
}

// 修改手势代理方法
extension YCPhotoPreviewCell: UIGestureRecognizerDelegate {
    override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if gestureRecognizer == panGesture {
            // 只有当图片未放大时才允许拖动手势
            if scrollView.zoomScale > 1.0 {
                return false
            }
            
            // 检查拖动方向
            let velocity = panGesture.velocity(in: scrollView)
            return isDragDirectionValid(velocity)
        }
        return true
    }
    
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        // 允许与CollectionView的滚动手势共存
        return gestureRecognizer != panGesture
    }
} 
